/* $Header: sig_ui.c,v 2.3 02/04/25 08:57:56 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1992                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME:  sig_ui.c                                              */
/* ============                                                        */
/*                                                                     */
/* Author:  Lesley Freed                                               */
/*                                                                     */
/* MODULE PURPOSE:  To provide the Set, Get, and Check functions for   */
/*                  the user interface to the signal path parameters.  */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include <typedefs.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <ramps.h>
#include <zone_config.h>
#include <i_op.h>
#include <zone_status.h>
#include <status.h>
#include <error.h>
#include <sig_types.h>
#include <sigpath.h>
#include <sig_ui.h>
#include <dig_path.h>
#include <messages.h>

#include <exception.h>
#include <glp.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/


/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/


/*****************************/
/*   STATIC VARIABLES        */
/*****************************/



/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/

INT32 GetSignalValue( pSIG_TABLE psignal )
{
      return ( (INT32)psignal->filt_out.output);
}

INT32 GetDisplayedSignalValue( pSIG_TABLE psignal )
{
   /* We will scale the signal so that it is displayed in meaningful units.   */
   /* We will only scale non-diagnostic type signals.  All other signals will */
   /* be displayed as they are stored.                                        */

   if ( ScaledSignal( psignal ) )
   {
      return ( (INT32)psignal->filt_out.output/SIG_DISP_SCALE_FACTOR );
   }
   else
   {
      return ( (INT32)psignal->filt_out.output)*10;
   }
}

SIG_UNITS GetSignalUnits( pSIG_TABLE psignal )
{
   return psignal->pscale->units;
}


U_INT16 GetSignalValueMsg( pSIG_TABLE psignal )
{
   U_INT16 msg;

   switch( GetSignalUnits( psignal ) )
   {
      case SIGNAL_D2:
         msg = SIGNAL_D2_VALUE_MSG;
         break;
      case SIGNAL_D3:
         msg = SIGNAL_D3_VALUE_MSG;
         break;
      case SIGNAL_D4:
         msg = SIGNAL_D4_VALUE_MSG;
         break;
      case SIGNAL_DET:
      default:
         msg = SIGNAL_VALUE_MSG;
   }

   return( msg );
}

static U_INT16 SignalZeroMsg( SIG_UNITS units )
{
   U_INT16 msg;

   switch( units )
   {
      case SIGNAL_D2:
         msg = SIGNAL_D2_ZERO_MSG;
         break;
      case SIGNAL_D3:
         msg = SIGNAL_D3_ZERO_MSG;
         break;
      case SIGNAL_D4:
         msg = SIGNAL_D4_ZERO_MSG;
         break;
      case SIGNAL_DET:
      default:
         msg = SIGNAL_ZERO_MSG;
   }
   return msg;
}

U_INT16 GetSignalZeroMsg( pSIG_TABLE psignal )
{
   return SignalZeroMsg( GetSignalUnits( psignal ) );
}



/***********************************************************************/
/* FUNCTION:   CheckSignalZero                                         */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To check that the signal zero setpoint is within range.   */
/*                                                                     */
/* RETURNED VALUE:  UI_ERR result code                                 */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

UI_ERR CheckSignalZero( INT32 zero )
{
   if ( zero > MAX_ZERO_VALUE )
   {
      return( PARAM_TOO_LARGE );
   }

   if ( zero < MIN_ZERO_VALUE )
   {
      return( PARAM_TOO_SMALL );
   }

   return( OK );
}

UI_ERR CheckScaledSignalZero( INT32 zero )
{
   if ( zero > MAX_DISP_ZERO_VALUE )
   {
      return( PARAM_TOO_LARGE );
   }

   if ( zero < MIN_DISP_ZERO_VALUE )
   {
      return( PARAM_TOO_SMALL );
   }

   return( OK );
}

UI_ERR CheckDisplaySignalZero( pSIG_TABLE psignal, INT32 zero )
{
   if ( ScaledSignal( psignal ) )
   {
      if ( zero > MAX_DISP_ZERO_VALUE )
      {
         return( PARAM_TOO_LARGE );
      }
      if ( zero < MIN_DISP_ZERO_VALUE )
      {
         return( PARAM_TOO_SMALL );
      }
   }
   else
   {
      if ( zero > MAX_UNSCALED_ZERO_VALUE )
      {
         return( PARAM_TOO_LARGE );
      }
      if ( zero < MIN_UNSCALED_ZERO_VALUE )
      {
         return( PARAM_TOO_SMALL );
      }
   }

   return( OK );

}

UI_ERR SetDisplaySignalZero( pSIG_TABLE psignal, INT32 zero )
{
   UI_ERR check_setpt;

   check_setpt = CheckDisplaySignalZero( psignal, zero );

   if ( check_setpt != OK )
   {
      return( check_setpt );
   }

   if ( ScaledSignal( psignal ) )
   {
      zero = zero*SIG_DISP_SCALE_FACTOR;
   }
   else
   {
      zero = zero/10;
   }

   return( SetSignalZero( psignal, zero ) );

}

UI_ERR SetSignalZero( pSIG_TABLE psignal, INT32 zero )
{
   UI_ERR check_setpt;

   check_setpt = CheckSignalZero( zero );

   if ( check_setpt != OK )
   {
      return( check_setpt );
   }

   INTERRUPTS_OFF

   psignal->active_wkfile->zero = zero;

   psignal->zero = zero;

   INTERRUPTS_ON

   if ( psignal->chan == SIGNAL1 )
   {
      LogSetptChange( SIGNAL1_ZERO, GetDisplayedSignalZero( psignal ), 0);
   }
   else if ( psignal->chan == SIGNAL2 )
   {
      LogSetptChange( SIGNAL2_ZERO, GetDisplayedSignalZero( psignal ), 0);
   }

   return( OK );

}

UI_ERR SetSignalZeroOff( pSIG_TABLE psignal )
{
   INTERRUPTS_OFF

   psignal->active_wkfile->zero_attn_on_off &= ZERO_OFF_MASK;

   psignal->zero_attn_on_off &= ZERO_OFF_MASK;

   INTERRUPTS_ON

   if ( psignal->chan == SIGNAL1 )
   {
      LogSetptChange( SIGNAL1_ZERO_OFF, 0, 0);
   }
   else if ( psignal->chan == SIGNAL2 )
   {
      LogSetptChange( SIGNAL2_ZERO_OFF, 0, 0);
   }

   return( OK );
}

UI_ERR SetSignalZeroOn( pSIG_TABLE psignal )
{
   INTERRUPTS_OFF

   psignal->active_wkfile->zero_attn_on_off |= ZERO_ON_MASK;
   psignal->zero_attn_on_off |= ZERO_ON_MASK;

   INTERRUPTS_ON

   if ( psignal->chan == SIGNAL1 )
   {
      LogSetptChange( SIGNAL1_ZERO_ON, 0, 0);
   }
   else if ( psignal->chan == SIGNAL2 )
   {
      LogSetptChange( SIGNAL2_ZERO_ON, 0, 0);
   }

   return( OK );
}

ON_OFF GetSignalZeroOnOff( pSIG_TABLE psignal )
{
   if ( psignal->zero_attn_on_off & ZERO_ON_MASK )
   {
      return ( ON );
   }
   else
   {
      return ( OFF );
   }
}



INT32 GetSignalZero( pSIG_TABLE psignal )
{
   return( psignal->zero );
}



INT32 GetDisplayedSignalZero( pSIG_TABLE psignal )
{
   /* We will only scale non-diagnostic type signals.  All other signals will */
   /* be displayed as they are stored.                                        */

   if ( ScaledSignal( psignal ) )
   {
      return ( (INT32)psignal->zero/SIG_DISP_SCALE_FACTOR );
   }
   else
   {
      return ( (INT32)psignal->zero )*10;
   }
}



UI_ERR SetAttnOnOff( pSIG_TABLE psignal, ON_OFF on_off )
{
   INTERRUPTS_OFF

   if ( on_off == OFF )
   {
      if ( psignal->chan == SIGNAL1 )
      {
         LogSetptChange( SIGNAL1_ATTN_OFF, 0, 0);
      }
      else if ( psignal->chan == SIGNAL2 )
      {
         LogSetptChange( SIGNAL2_ATTN_OFF, 0, 0);
      }
      psignal->active_wkfile->zero_attn_on_off &= ~ATTN_ON_MASK;
   }
   else
   {
      if ( psignal->chan == SIGNAL1 )
      {
         LogSetptChange( SIGNAL1_ATTN_ON, 0, 0);
      }
      else if ( psignal->chan == SIGNAL2 )
      {
         LogSetptChange( SIGNAL2_ATTN_ON, 0, 0);
      }
      psignal->active_wkfile->zero_attn_on_off |= ATTN_ON_MASK;
   }

   psignal->zero_attn_on_off = psignal->active_wkfile->zero_attn_on_off;

   INTERRUPTS_ON


   return( OK );
}

ON_OFF GetAttnOnOff( pSIG_TABLE psignal )
{
   if ( psignal->zero_attn_on_off & ATTN_ON_MASK )
   {
      return( ON );
   }

   return( OFF );

}


UI_ERR CheckSignalAttn( INT32 attn )
{
   if ( attn < MIN_ATTN_SETPT )
   {
      return( PARAM_TOO_SMALL );
   }
   else
   {
      if ( attn > MAX_ATTN_SETPT )
      {
         return( PARAM_TOO_LARGE );
      }
      else
      {
         return( OK );
      }
   }
}

UI_ERR SetSignalAttn( pSIG_TABLE psignal, INT32 attn )
{

   UI_ERR ui_err;

   ui_err = CheckSignalAttn( attn );

   if ( ui_err != OK )
   {
      return( ui_err );
   }

   INTERRUPTS_OFF                       /* protect change */

   psignal->active_wkfile->attn = (U_INT8)attn;
   psignal->attn = (U_INT8)attn;
   psignal->active_wkfile->zero_attn_on_off |= ATTN_ON_MASK;
   psignal->zero_attn_on_off = psignal->active_wkfile->zero_attn_on_off;

   INTERRUPTS_ON                        /* release protection */

   if ( psignal->chan == SIGNAL1 )
   {
      LogSetptChange( SIGNAL1_ATTN, attn, 0);
   }
   else if ( psignal->chan == SIGNAL2 )
   {
      LogSetptChange( SIGNAL2_ATTN, attn, 0);
   }

   return( OK );

}

INT32 GetSignalAttn( pSIG_TABLE psignal )
{
   return ( (INT32)psignal->attn );
}


UI_ERR CheckSignalRange( INT32 range )
{
   if ( range < MIN_RANGE_SETPT )
   {
      return( PARAM_TOO_SMALL );
   }
   else
   {
      if ( range > MAX_RANGE_SETPT )
      {
         return( PARAM_TOO_LARGE );
      }
      else
      {
         return( OK );
      }
   }
}


UI_ERR SetSignalRange( pSIG_TABLE psignal, INT32 range )
{
   UI_ERR ui_err;

   ui_err = CheckSignalRange( range );

   if ( ui_err != OK )
   {
      return( ui_err );
   }

   INTERRUPTS_OFF                       /* protect change */

   psignal->active_wkfile->range = (U_INT8)range;
   psignal->range = (U_INT8)range;

   INTERRUPTS_ON                        /* release protection */


   if ( psignal->chan == SIGNAL1 )
   {
      LogSetptChange( SIGNAL1_RANGE, range, 0);
   }
   else if ( psignal->chan == SIGNAL2 )
   {
      LogSetptChange( SIGNAL2_RANGE, range, 0);
   }

   return( OK );

}

INT32 GetSignalRange( pSIG_TABLE psignal )
{
   return ( (INT32)psignal->range );
}



/***********************************************************************/
/* FUNCTION:  SetFastPeaks                                             */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To set the bandwidth for the DAC output.                  */
/*                                                                     */
/* RETURNED VALUE:  UI_ERR return code                                 */
/*                                                                     */
/* GLOBALS USED:  Signal1_Setpts                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/

UI_ERR CheckFastPeaks( BIT32 rate )
{
   if ( ( rate == DAC_RATE_3HZ )  ||
        ( rate == DAC_RATE_30HZ ) )
   {
      return( OK );
   }

   return( INVALID_PARAM );
}

UI_ERR SetFastPeaks( pSIG_TABLE psignal, BIT32 rate )
{
   UI_ERR check_setpt;

   check_setpt = CheckFastPeaks( rate );

   if ( check_setpt != OK )
   {
      return( check_setpt );
   }

   INTERRUPTS_OFF

   psignal->active_wkfile->DAC_rate = rate;

   INTERRUPTS_ON

   if ( rate == DAC_RATE_3HZ )
   {
      if ( psignal->chan == SIGNAL1 )
      {
         LogSetptChange( SIGNAL1_FAST_PEAKS_OFF, 0, 0);
      }
      else if ( psignal->chan == SIGNAL2 )
      {
         LogSetptChange( SIGNAL2_FAST_PEAKS_OFF, 0, 0);
      }
   }
   else
   {
      if ( psignal->chan == SIGNAL1 )
      {
         LogSetptChange( SIGNAL1_FAST_PEAKS_ON, 0, 0);
      }
      else if ( psignal->chan == SIGNAL2 )
      {
         LogSetptChange( SIGNAL2_FAST_PEAKS_ON, 0, 0);
      }
   }

   return( OK );
}

BIT32 GetFastPeaks( pSIG_TABLE psignal )
{
   return( psignal->active_wkfile->DAC_rate );
}



/***********************************************************************/
/* FUNCTION:  SetSignalDataRate                                        */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:   To change the data rate of a signal.                     */
/*                                                                     */
/* RETURNED VALUE:  The active workfile data rate and the working      */
/*                  setpoint data rate.                                */
/*                                                                     */
/* GLOBALS USED:  SIG_TABLE Signal1/2, Active_Wkfile                   */
/*                                                                     */
/* LIMITATIONS:  This function will reset the bunch sum and bunch      */
/*               count.  This will prevent erroneous signal output     */
/*               from the bunching for no signal rate change (setting  */
/*               the rate to what it all ready is) and will give       */
/*               an intermediate value between the old signal type and */
/*               the new signal type value if the signal type has also */
/*               changed.  The data will NOT be correct for a signal   */
/*               rate change however.  It will required 6 data points  */
/*               for the data through the buncher boxcar filter to be  */
/*               correct.                                              */
/*                                                                     */
/***********************************************************************/


/* First we will define the signal rate lookup table.  This is used    */
/* translating the incoming data rate parameter into the working rate  */
/* setpt for the signal DSP and bunch count for the signal path.       */

const RATE_REC RATE_TABLE[] =
{
  /* Rate */ /* bunch */
      4,         200,         /* .1   Hz = 20 Hz raw / 200 */
      4,         100,         /* .2   Hz = 20 Hz raw / 100 */
      4,         40,          /* .5   Hz = 20 Hz raw / 50  */
      4,         20,          /*  1   Hz = 20 Hz raw / 20  */
      4,         10,          /*  2   Hz = 20 Hz raw / 10  */
      4,         4,           /*  5   Hz = 20 Hz raw / 4   */
      4,         2,           /* 10   Hz = 20 Hz raw / 2   */
      3,         0,           /* 20   Hz = 20 Hz       */
      2,         0,           /* 50   Hz */
      1,         0,           /* 100  Hz */
      0,         0,           /* 200  Hz */
      5,         0,           /* 500  Hz */
      6,         0            /* 1000 Hz */
};

UI_ERR CheckSignalDataRate( RATE_TYPE rate )
{
   if ( ( rate < MIN_DATA_RATE ) || ( rate > MAX_DATA_RATE ) )
   {
      return( INVALID_PARAM );
   }
   else
   {
         return( OK );
   }
}

UI_ERR SetSignalDataRate( pSIG_TABLE psignal, RATE_TYPE rate )
{
   UI_ERR ui_err;

   ui_err = CheckSignalDataRate( rate );

   if ( ui_err != OK )
   {
      return( ui_err );
   }

   INTERRUPTS_OFF

   /* Only reset the buncher if the data rate has changed and we are bunching */
   if ( rate < RATE_20HZ )
   {
      if ( psignal->active_wkfile->rate != (BIT8)rate )
      {
         /* Reset the bunch state */
         psignal->bunch_count         = 0;
         psignal->bunch_sum.hi        = 0;
         psignal->bunch_sum.lo        = 0;
         psignal->bunch_out.remainder = 0;
         psignal->bunch_reset = TRUE;  /* Flag that the data rate has changed */
      }
   }
   else
   {
      psignal->bunch_reset = FALSE;
   }

   psignal->active_wkfile->bunch_count = RATE_TABLE[(U_INT16)rate].bunch_count;
   psignal->active_wkfile->rate = (BIT8)rate;

   if ( psignal == pSIGNAL1 )
   {
      Dsp_Out.sig1_rate = RATE_TABLE[(U_INT16)rate].rate;
   }
   else
   {
      Dsp_Out.sig2_rate = RATE_TABLE[(U_INT16)rate].rate;
   }

   INTERRUPTS_ON

   if ( psignal->chan == SIGNAL1 )
   {
      LogSetptChange( SIGNAL1_DATA_RATE, (INT32)rate, 0);
   }
   else if ( psignal->chan == SIGNAL2 )
   {
      LogSetptChange( SIGNAL2_DATA_RATE, (INT32)rate, 0);
   }

   return( OK );

}

RATE_TYPE GetSignalDataRate( pSIG_TABLE psignal )
{
   return( (RATE_TYPE)psignal->active_wkfile->rate );
}


/****************************/
/* Set/Get utility routines */
/****************************/

BIT8 UnscaledSignal( SIG_TYPE type )
{
   if ( type < FIRST_UNSCALED_SIGNAL )
   {
      return ( FALSE );
   }

   return( TRUE );
}

BIT8 ScaledSignal( pSIG_TABLE psignal )
{
   if ( psignal->signal < FIRST_UNSCALED_SIGNAL )
   {
      return ( TRUE );
   }

   return( FALSE );
}

BIT8 AlternateSignal( SIG_TYPE type )
{
   if ( type < FIRST_ALTERNATE_SIGNAL )  return FALSE;
   return TRUE;
}

SIG_UNITS GetSignalUnitsFromType( SIG_TYPE type )
{
   SCALE_CONSTANTS const *pscale;

   pscale = GetSignalScaleFactor( type );

   return pscale->units;
}

